package com.bb.flow.config;

import com.bb.flow.api.entries.FlowContext;

import java.util.HashMap;
import java.util.Map;

/**
 * @author bigbeard
 * 流程对象
 */
public class FlowInfo {
    /**
     * 流程节点
     */
    private final Map<String, AbstractConfigNode> flowNodes = new HashMap<>();
    /**
     * 创建此流程的json文件
     */
    private String flowTextInfo;
    /**
     * 流程节点上下文对象
     */
    private FlowContext flowContext = null;
    /**
     * 流程模版名称
     */
    private String flowTemplateName;
    /**
     * 流程实例名称
     */
    private String flowInstanceName;
    /**
     * 启动条件
     */
    private ConditionInfo condition;
    /**
     * 是否取消执行
     */
    private volatile boolean isCancelExecute = false;
    /**
     * 父流程
     */
    private FlowInfo parentFlow = null;
    /**
     * 流程附加信息
     */
    private String otherInfo;

    /**
     * 流程附加信息
     *
     * @return 配置到流程上的附加信息说明
     */
    public String getOtherInfo() {
        return otherInfo;
    }

    public void setOtherInfo(String otherInfo) {
        this.otherInfo = otherInfo;
    }

    /**
     * 获取父流程
     *
     * @return 父流程
     */
    public FlowInfo getParentFlow() {
        return this.parentFlow;
    }


    /**
     * 设置父流程
     *
     * @param flowInfo 父流程
     */
    public void setParentFlow(FlowInfo flowInfo) throws Exception {
        if (flowInfo.hashCode() == this.hashCode()) {
            throw new Exception("父流程不能是自己");
        }
        this.parentFlow = flowInfo;
    }

    /**
     * 上下文信息
     *
     * @return 上下文信息
     */
    public FlowContext getFlowContext() {
        return flowContext;
    }

    /**
     * 设置上下文信息
     *
     * @param flowContext 上下文内容
     * @return 当前对象
     */
    public FlowInfo setFlowContext(FlowContext flowContext) {
        this.flowContext = flowContext;
        return this;
    }

    /**
     * 获取流程实例名称
     *
     * @return 实例名称
     */
    public String getFlowInstanceName() {
        return this.flowInstanceName;
    }

    /**
     * 设置流程实例名称
     *
     * @param flowInstanceName 实例名称
     * @return 当前对象
     */
    public FlowInfo setFlowInstanceName(String flowInstanceName) {
        this.flowInstanceName = flowInstanceName;
        return this;
    }

    /**
     * 是否取消
     *
     * @return true:取消执行,false没有取消
     */
    public boolean isCancelExecute() {
        return isCancelExecute;
    }

    /**
     * 设置取消执行
     *
     * @param cancelExecute true:取消执行,false 未取消执行
     * @return 当前对象
     */
    public FlowInfo setCancelExecute(boolean cancelExecute) {
        isCancelExecute = cancelExecute;
        return this;
    }


    /**
     * 获取启动条件
     *
     * @return 返回启动条件
     */
    public ConditionInfo getCondition() {
        return condition;
    }

    /**
     * 设置启动条件
     *
     * @param condition 条件对象
     * @return 当前对象
     */
    public FlowInfo setCondition(ConditionInfo condition) {
        this.condition = condition;
        return this;
    }

    public Map<String, AbstractConfigNode> getFlowNodes() {
        return flowNodes;
    }


    /**
     * 流程模版名称
     *
     * @return 流程模版名称
     */
    public String getFlowTemplateName() {
        return flowTemplateName;
    }

    /**
     * 设置流程名词,整个驱动内需要唯一
     *
     * @param flowTemplateName 流程模版名称
     * @return 当前对象
     */
    public FlowInfo setFlowTemplateName(String flowTemplateName) {
        this.flowTemplateName = flowTemplateName;
        return this;
    }

    /**
     * 获取创建此流程的配置信息
     *
     * @return 配置信息
     */
    public String getFlowTextInfo() {
        return flowTextInfo;
    }

    /**
     * 设置创建当前流程的配置信息
     *
     * @param flowTextInfo 配置信息
     * @return 当前对象
     */
    public FlowInfo setFlowTextInfo(String flowTextInfo) {
        this.flowTextInfo = flowTextInfo;
        return this;
    }


    /**
     * 移除指定流程节点
     *
     * @param nodeKey 节点编号
     */
    public void removeFlowNode(String nodeKey) {
        flowNodes.remove(nodeKey);
    }

    /**
     * 添加流程接点
     *
     * @param node 节点对象,如果流程节点的名称和已有流程接点重名则覆盖已有流程接点
     */
    public void addFlowNode(AbstractConfigNode node) {
        removeFlowNode(node.getNodeKey());
        flowNodes.put(node.getNodeKey(), node);
    }

    /**
     * 覆盖原来所有流程节点,不论是否重名
     *
     * @param map 新的流程节点
     */
    public void addFlowNode(Map<String, AbstractConfigNode> map) {
        flowNodes.clear();
        flowNodes.putAll(map);
    }
}
